/*
RetroLeague - Mobile application for The Retro League Podcast
Copyright (C) 2010-2012 Hugues Johnson

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software 
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

package com.huguesjohnson.retroleague;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

import com.huguesjohnson.retroleague.episode.Episode;
import com.huguesjohnson.retroleague.episode.EpisodeParser;
import com.huguesjohnson.retroleague.util.HttpFetch;
import com.huguesjohnson.retroleague.util.SerializationHelper;

public class EpisodeListActivity extends Activity{
	private final static String TAG="EpisodeListActivity";
	private ArrayList<Episode> episodes;
	//ui stuff
	private AlertDialog aboutDialog;
	private ImageView imageViewEpisodeListLatestEpisode;
	private ProgressBar progressBarDownloadingEpisodeList;
	private TextView textViewDownloadingEpisodeList;
	//menu constants
	private final static int MENU_BACK=0;
	private final static int MENU_ABOUT=1;
	private final static int MENU_REFRESH=2;
	//currently playing episode - needs to be accessible to NowPlayingActivity
	private static Episode selectedEpisode;
	public static void setSelectedEpisode(Episode e){selectedEpisode=e;}
	public static Episode getSelectedEpisode(){return(selectedEpisode);}

	private class DownloadLatestEpisodeImageTask extends AsyncTask<String,String,Bitmap>{
		public Bitmap doInBackground(String... urls){
			try{
				Log.d(TAG,"DownloadLatestEpisodeImageTask.doInBackground, urls[0]="+urls[0]);
				Bitmap bitmap=ImageCache.get(urls[0]);
				if(bitmap!=null){return(bitmap);}
        		long startTime=System.currentTimeMillis();
				bitmap=HttpFetch.fetchBitmap(urls[0]);
        		long endTime=System.currentTimeMillis();
        		Log.d(TAG,"DownloadLatestEpisodeImageTask.doInBackground, Time to fetch bitmap="+(endTime-startTime)+"ms");
				ImageCache.put(urls[0],bitmap);
                return(bitmap);
			}catch(Exception x){
				Log.e(TAG,"DownloadLatestEpisodeImageTask",x);
    	    	return(null);
			}
	     }

	     public void onPostExecute(Bitmap result){
	    	 if(result!=null){
		    	 Log.d(TAG,"DownloadLatestEpisodeImageTask.onPostExecute, result..toString()="+result.toString()+", result dimensions="+result.getWidth()+","+result.getHeight());
	    	 }else{
		    	 Log.d(TAG,"DownloadLatestEpisodeImageTask.onPostExecute, image is null");
	    	 }
	    	 imageViewEpisodeListLatestEpisode.setImageBitmap(result);
	     }
	 }

	private class DownloadEpisodeListTask extends AsyncTask<String,String,Void>{
		public Void doInBackground(String... params){
        	HttpURLConnection httpConnection=null;
        	InputStream httpIn=null;
        	try{
				Log.d(TAG,"DownloadEpisodeListTask.doInBackground");
        		long startTime=System.currentTimeMillis();
        		URL url=new URL(getResources().getString(R.string.rss_url));
                httpConnection=(HttpURLConnection)url.openConnection();
                httpConnection.setConnectTimeout(10000);
        		long endTime=System.currentTimeMillis();
                Log.d(TAG,"DownloadEpisodeListTask.DownloadEpisodeListTask.doInBackground - Time to open connection="+(endTime-startTime)+"ms");
                startTime=endTime;
                httpIn=httpConnection.getInputStream();
        		endTime=System.currentTimeMillis();
                Log.d(TAG,"DownloadEpisodeListTask.DownloadEpisodeListTask.doInBackground - Time to get input stream="+(endTime-startTime)+"ms");
                startTime=endTime;
                episodes=EpisodeParser.parseEpisodeList(httpIn);
        		endTime=System.currentTimeMillis();
                Log.d(TAG,"DownloadEpisodeListTask.DownloadEpisodeListTask.doInBackground - Time to parse episode list="+(endTime-startTime)+"ms");
                httpIn.close();
        		httpConnection.disconnect();
            }catch(Exception x){
    			Log.e(TAG,"DownloadEpisodeListTask.DownloadEpisodeListTask.doInBackground",x);
            	//in case the IOException is thrown by one of the HttpURLConnection operations
            	if(httpConnection!=null){
            		httpConnection.disconnect();
            	}
            }
    		return(null);
	     }

	     @SuppressWarnings("unchecked")
		public void onPostExecute(Void result){
    		if((episodes!=null)&&(episodes.size()>0)){
    			updateUI();
    			SerializationHelper.serializeObject(episodes,"episodes.obj");
    		}else{ //some kind of problem getting the episodes, revert to most recent good copy
        		ArrayList<Episode> cachedEpisodes=(ArrayList<Episode>)SerializationHelper.readObject("episodes.obj");
        		if(cachedEpisodes!=null){
        			episodes=cachedEpisodes;
        			updateUI();
        		}else{
        			showErrorDialog(new Exception("Unable to download episode list. Please check your internet connectivity and retry."));
        			return;
        		}
    		}
    	}	
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu){
		try{
			menu.add(0,MENU_ABOUT,0,"About").setIcon(R.drawable.menu_about);
			menu.add(0,MENU_REFRESH,1,"Refresh").setIcon(R.drawable.menu_refresh);
			menu.add(0,MENU_BACK,2,"Back to main menu").setIcon(R.drawable.menu_back);
			return(true);
		}catch(Exception x){
			Log.e(TAG,"onCreateOptionsMenu",x);
			return(false);
		}
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item){
		try{
			switch(item.getItemId()){
			case MENU_REFRESH:{this.refreshEpisodeList();return(true);}
			case MENU_ABOUT:{this.showAboutDialog(); return(true);}
			case MENU_BACK:{this.finish();return(true);}
			default:{return(false);}
			}
		}catch(Exception x){
			if(item!=null){
				Log.e(TAG,"onOptionsItemSelected: item.getItemId()="+item.getItemId(),x);
			}else{
				Log.e(TAG,"onOptionsItemSelected: item is null",x);
			}
			return(false);
		}
	}
	
	OnItemClickListener selectEpisodeListener=new OnItemClickListener(){
		@Override
		public void onItemClick(AdapterView<?> parent,View view,int position,long id){
			try{
				episodeClicked(position);
			}catch(Exception x){
				Log.e(TAG,"onItemClick: position="+position,x);
				showErrorDialog(x);
			}
		}
	};
	
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.episodelistlayout);
        ListView listViewEpisodeListAllEpisodes=(ListView)findViewById(R.id.ListViewEpisodeListAllEpisodes);
        listViewEpisodeListAllEpisodes.setOnItemClickListener(selectEpisodeListener);
		TextView textViewEpisodeListLatestEpisode=(TextView)findViewById(R.id.TextViewEpisodeListLatestEpisode);
		textViewEpisodeListLatestEpisode.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v){
				episodeClicked(0);
			}
		});
		this.imageViewEpisodeListLatestEpisode=(ImageView)findViewById(R.id.ImageViewEpisodeListLatestEpisode);
		this.imageViewEpisodeListLatestEpisode.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v){
				episodeClicked(0);
			}
		});
		this.progressBarDownloadingEpisodeList=(ProgressBar)findViewById(R.id.ProgressBarDownloadingEpisodeList);
		this.textViewDownloadingEpisodeList=(TextView)findViewById(R.id.TextViewDownloadingEpisodeList);
    }

    private void refreshEpisodeList(){
		//launch a dialog and thread
		try{
			this.textViewDownloadingEpisodeList.setVisibility(View.VISIBLE);
			this.progressBarDownloadingEpisodeList.setVisibility(View.VISIBLE);
			this.textViewDownloadingEpisodeList.setText(this.getResources().getString(R.string.status_downloading_episode_list));
			new DownloadEpisodeListTask().execute("");
		}catch(Exception x){
			Log.e(TAG,"refreshEpisodeList",x);
			this.textViewDownloadingEpisodeList.setText(x.getMessage());
		}
	}
    
	@Override
	protected void onResume(){
		super.onResume();
		//in case we came here after the user navigated away by clicking on the site link in the about dialog
		if((aboutDialog!=null)&&(aboutDialog.isShowing())){
			return;
		}
		//load the episode list
		if((this.episodes==null)||(this.episodes.size()<1)){
			this.refreshEpisodeList();
		}
	}
	
	private void updateUI(){
		if((this.episodes==null)||(this.episodes.size()<1)){
			this.textViewDownloadingEpisodeList.setVisibility(View.VISIBLE);
			this.progressBarDownloadingEpisodeList.setVisibility(View.GONE);
			this.textViewDownloadingEpisodeList.setText(this.getResources().getString(R.string.status_no_episodes));
		}else{ 
			//hide the progress fields
			this.textViewDownloadingEpisodeList.setVisibility(View.GONE);
			this.progressBarDownloadingEpisodeList.setVisibility(View.GONE);
			//show labels
			TextView textViewEpisodeListLatestEpisodeLabel=(TextView)findViewById(R.id.TextViewEpisodeListLatestEpisodeLabel);
			textViewEpisodeListLatestEpisodeLabel.setVisibility(TextView.VISIBLE);
			TextView textViewEpisodeListPreviousEpisodesLabel=(TextView)findViewById(R.id.TextViewEpisodeListPreviousEpisodesLabel);
			textViewEpisodeListPreviousEpisodesLabel.setVisibility(TextView.VISIBLE);
			//display the current episode information
			Episode latestEpisode=this.episodes.get(0);
			//episode title
			TextView textViewEpisodeListLatestEpisode=(TextView)findViewById(R.id.TextViewEpisodeListLatestEpisode);
			textViewEpisodeListLatestEpisode.setText(latestEpisode.getTitle());
			//image
			this.imageViewEpisodeListLatestEpisode.setImageDrawable(this.getResources().getDrawable(R.drawable.downloading));
			new DownloadLatestEpisodeImageTask().execute(latestEpisode.getImageUrl());
			//previous episodes
			EpisodeListArrayAdapter adapter=new EpisodeListArrayAdapter(this.getApplicationContext(),R.layout.episodelistitem,this.episodes);
			ListView listViewEpisodeListAllEpisodes=(ListView)findViewById(R.id.ListViewEpisodeListAllEpisodes);
			listViewEpisodeListAllEpisodes.setAdapter(adapter);
		}
	}
	
	private void episodeClicked(int episodeIndex){
		try{
			setSelectedEpisode(this.episodes.get(episodeIndex));
			Intent nowPlayingIntent=new Intent(this.getApplicationContext(),NowPlayingActivity.class);
			this.startActivityForResult(nowPlayingIntent,0);
		}catch(Exception x){
			Log.e(TAG,"episodeClicked, episodeIndex="+episodeIndex,x);
			this.showErrorDialog(x);
		}
	}
    
	private void showErrorDialog(Exception x){
		try{
	        new AlertDialog.Builder(this)
	   		.setTitle(R.string.app_name)
	   		.setMessage(x.getMessage())
	   		.setPositiveButton("Close", null)
	   		.show();	
		}catch(Exception reallyBadTimes){
			Log.e(TAG,"showErrorDialog",reallyBadTimes);
		}
	}
	
	private void showAboutDialog(){
		try{
			//create the dialog
			if(this.aboutDialog==null){
				LayoutInflater inflater=(LayoutInflater)this.getSystemService(LAYOUT_INFLATER_SERVICE);
				View layout=inflater.inflate(R.layout.aboutdialoglayout,(ViewGroup)findViewById(R.id.AboutDialogRoot));
				AlertDialog.Builder builder=new AlertDialog.Builder(this);
				builder.setView(layout);
				builder.setTitle("About");
				builder.setPositiveButton("Close",null);
				this.aboutDialog=builder.create();
			}
			//show the dialog
			this.aboutDialog.show();
		}catch(Exception x){
			Log.e(TAG,"showAboutDialog",x);
		}	
	}
}